/*
 * Copyright (C) 2011 by ayoung <ayoung.p@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.peaceb.ruletherain;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.os.Handler;
import android.os.Message;

public class Engine {
    public static final int STATE_NONE      = 0;
    public static final int STATE_READY     = 1;
    public static final int STATE_WORKING   = 2;
    public static final int STATE_STOPPING  = 3;
    
    public static final int MSG_UPDATE      = 0; /* one city was updated in update all processing */
    public static final int MSG_DONE        = 1; /* update all done */
    public static final int MSG_DONE_ONE    = 2; /* update done */
    public static final int MSG_DELETE_DONE = 3;
    public static final int MSG_SAVE_DONE   = 4;
    public static final int MSG_ERROR       = 5; 
    
    private RuleTheRainApplication mApplication;
    private Handler                mHandler;
    private int                    mUpdateState;
    private int                    mServiceState = STATE_NONE;
    private String                 mCurrentCity = "None";
    
    public Engine(RuleTheRainApplication context) {
        Trace.v(this, "Engine()");
        
        mApplication = context;
        
        setUpdateState(STATE_READY);
    }
    
    /**
     * Set handler
     * 
     * @param handler
     */
    public void setHandler(Handler handler) {
        mHandler = handler;
    }
    
    /**
     * Set engine state
     * 
     * @param state
     */
    public void setUpdateState(int state) {
        if (state == STATE_STOPPING && mUpdateState != STATE_WORKING) {
            Trace.i("not working state");
            return;
        }
        mUpdateState = state;
    }
    
    /**
     * Get engine state
     * 
     * @return
     */
    public int getUpdateState() {
        return mUpdateState;
    }
    
    /**
     * Get fake location service state
     * 
     * @return
     */
    public int getServiceState() {
        return mServiceState;
    }
    
    /**
     * dump current location
     */
    public void dumpCurrentLocation() {
        Location location = null;
        LocationManager lm = (LocationManager)mApplication.getSystemService(Context.LOCATION_SERVICE);
        
        List<String> providers = lm.getAllProviders();
        for (String provider : providers) {
            Location loc = lm.getLastKnownLocation(provider);
            if (loc != null) {
                Trace.i("provider: " + provider);
                location = loc;
                break;
            }
        }
        
        if (location != null) {
            Trace.i(location.toString());
        }
        else {
            Trace.w("location is null");
        }
    }
    
    /**
     * Get weather infomation
     * 
     * @param handler
     * @return
     */
    public int getWeatherData(Handler handler) {
        mHandler = handler;
        ArrayList<WeatherInfo> cityList = mApplication.getCityList();
        if (getUpdateState() != STATE_READY) {
            Trace.i("Engine state is not ready: " + getUpdateState());
            return C.ERROR;
        }
        
        setUpdateState(STATE_WORKING);
        for (WeatherInfo city : cityList) {
            if (getUpdateState() == STATE_WORKING) {
                if (HttpHelper.HttpGet(city) == C.SUCCESS) {
                    Parser.parse(city);
                    Trace.i(city.cityName + " " + city.weatherCode);
                    mHandler.sendEmptyMessage(MSG_UPDATE);
                }
            }
        }
        
        mHandler.sendEmptyMessage(MSG_DONE);
        setUpdateState(STATE_READY);
        
        return C.SUCCESS;
    }
    
    /**
     * Get weather data for one city
     * 
     * @param handler
     * @param info
     * @return
     */
    public int getWeatherDataOne(Handler handler, WeatherInfo info) {
        if (HttpHelper.HttpGet(info) == C.SUCCESS) {
            Parser.parse(info);
            handler.sendEmptyMessage(MSG_DONE_ONE);
        }
        else {
            handler.sendEmptyMessage(MSG_ERROR);
        }
        return C.SUCCESS;
    }
    
    /**
     * Get weather information for add activity
     * 
     * @param handler
     * @return
     */
    public int getWeatherDataForAdd(Geocoder geoCoder, WeatherInfo city, Handler handler) {
        if (HttpHelper.HttpGet(city) == C.SUCCESS) {
            Parser.parse(city);
            
            try {
                List<Address> list = geoCoder.getFromLocationName(city.cityName, 1);
                if (list.size() > 0) {
                    Address address = list.get(0);
                    city.latitude  = address.getLatitude();
                    city.longitude = address.getLongitude();
                    city.altitude  = 0; /* not used */
                }
            } 
            catch (IOException e) {
                Trace.e(this, e.toString());
            }
            
            Message msg = Message.obtain();
            msg.what = MSG_DONE;
            msg.obj  = city;
            handler.sendMessage(msg);
        }
        else {
            handler.sendEmptyMessage(MSG_ERROR);
        }
        
        return C.SUCCESS;
    }
    
    /**
     * Get current city
     * 
     * @return
     */
    public String getCurrentCity() {
        return mCurrentCity;
    }
    
    /**
     * Set current city
     * 
     * @param cityName
     */
    public void setCurrentCity(String cityName) {
        mCurrentCity = cityName;
    }
}
